from datetime import timedelta
from datetime import datetime
from src.settings import setting
from jose import jwt
from .models import UserInfo
from fastapi.security import OAuth2PasswordBearer
from fastapi.requests import Request
from src.utils.common_exception import AuthException
from fastapi import Depends

oaauth2 = OAuth2PasswordBearer(tokenUrl='token')


def create_access_token(data: dict, expires_delta=None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(setting.ACCESS_TOKEN_EXPIRE_MINUTES)

    to_encode.update({'exp': expire})
    encode_jwt = jwt.encode(to_encode, setting.SECRET_KEY, algorithm=setting.ALGORITHM)
    return encode_jwt


async def authenticate_user(username: str, password: str):
    user: UserInfo = await UserInfo.get_or_none(username=username)
    if not user:
        return False
    if not user.check_password(password):
        return False
    if user.is_active:
        return user
    else:
        return False


async def oaauth2_achema(request: Request):
    try:
        token = await oaauth2(request)
        return token
    except Exception as e:
        raise AuthException(msg='用户必须携带token')


async def get_current_user(token: str = Depends(oaauth2_achema)):
    try:
        payload = jwt.decode(token, setting.SECRET_KEY, algorithms=[setting.ALGORITHM])
        username: str = payload.get('username')
        if username is None:
            raise AuthException(msg="验证失败")
        user = await UserInfo.get_or_none(username=username)
    except jwt.JWTError:
        raise AuthException(msg="验证失败")

    return user
